<?php declare(strict_types=1);

namespace App\Task\Task;

use Swoft\Task\Annotation\Mapping\Task;
use Swoft\Task\Annotation\Mapping\TaskMapping;
use App\Model\Kid\KidPhysicalTestScore as KidPhysicalTestScoreModel;
use App\Model\Kid\KidPhysicalTestResult as KidPhysicalTestResultModel;
use App\Model\Kid\KidInstitution as KidInstitutionModel;
use App\Model\PhysicalTest\PhysicalTestProject as PhysicalTestProjectModel;
use App\Model\PhysicalTest\PhysicalTest as PhysicalTestModel;
use App\Model\Project\ProjectScoreName as ProjectScoreNameModel;
use App\Model\PhysicalTest\PhysicalTestScoreName as PhysicalTestScoreNameModel;
use Swoft\Db\DB;

/**
 * 小孩体测任务
 * Class KidPhysicalTestTask
 * @Task(name="KidPhysicalTestTask")
 */
class KidPhysicalTestTask
{

        /**
         * @TaskMapping(name="actKidPhysicalTest")
         * 处理完成
         * @param $strInstitutionId
         * @param $strPhysicalTestId
         */
        public function actKidPhysicalTest($strInstitutionId, $strPhysicalTestId)
        {
                //获取这个体测下面的所有班级
                $arrWhere = [
                        'physical_test.institutionId' => $strInstitutionId,
                        'physical_test.physicalTestId' => $strPhysicalTestId,
                ];
                $arrJoin = [
                        'physical_test_classes' => [
                                'table' => 'physical_test_classes',
                                'where' => ['physical_test_classes.physicalTestId', '=', 'physical_test.physicalTestId']
                        ],
                ];
                $arrField = ['physical_test_classes.classesId'];
                $arrClasses = PhysicalTestModel::getAll($arrWhere, $arrField, [], [], $arrJoin);
                //加入体测的开始时间
                $arrWhere = ['physicalTestId' => $strPhysicalTestId];
                $intStartTime = PhysicalTestModel::getFieldValue($arrWhere, 'startTime');
                foreach ($arrClasses as $k => $v) {
                        $strClassesId = $v['classesId'];
                        sgo(function () use ($strInstitutionId, $strPhysicalTestId, $strClassesId, $intStartTime) {
                                $arrReturn = $this->actKidPhysicalTestResult($strInstitutionId, $strPhysicalTestId, $strClassesId, $intStartTime);
                        });
                }

                //处理体测项目的分数对应的名称
                $arrReturn = $this->actPhysicalTestScoreName($strPhysicalTestId);
        }

        /**
         * 处理体测结果排名
         * @param $strInstitutionId
         * @param $strPhysicalTestId
         * @param $strClassesId
         * @throws \Exception
         */
        public function actKidPhysicalTestResult($strInstitutionId, $strPhysicalTestId, $strClassesId, $intStartTime)
        {
                $intTime = time();
                //获取这个体测下面这个班级所有的学生
                $arrWhere = [
                        'classesId' => $strClassesId,
                        'institutionId' => $strInstitutionId,
                ];
                $arrField = ['kidId'];
                $arrClassesKid = KidInstitutionModel::getAll($arrWhere, $arrField);
                $arrAllClassesKid = array_column($arrClassesKid, 'kidId');

                //获取该班级下面已经做过测试的小孩
                $arrWhere['physicalTestId'] = $strPhysicalTestId;
                $arrField = ['kidPhysicalTestResultId', 'kidId', 'score', 'projectId', 'ranking', 'upTime'];
                $arrPhysicalTestResult = KidPhysicalTestResultModel::getAll($arrWhere, $arrField);
                //提取已经做过体测的小孩
                $arrPhysicalTestKid = array_column($arrPhysicalTestResult, 'kidId');
                $arrPhysicalTestKid = array_unique($arrPhysicalTestKid);

                //获取该体测的所有项目
                $arrWhere = [
                        'physicalTestId' => $strPhysicalTestId,
                ];
                $arrField = ['projectId'];
                $arrProject = PhysicalTestProjectModel::getAll($arrWhere, $arrField);
                //$arrProjectId = array_column($arrProject,'projectId');

                //获取小孩已经做了的项目
                $arrPhysicalTestProject = [];
                //以项目为依据获取该项目下面所有小孩
                $arrKidResultProject = [];
                foreach ($arrPhysicalTestResult as $k => $v) {
                        $kidId = $v['kidId'];
                        $projectId = $v['projectId'];
                        $arrPhysicalTestProject[$kidId][] = $v;
                        $arrKidResultProject[$projectId][] = $v;

                }

                //计算项目的排名(更新的项目)
                $arrUpdateProjectRank = [];
                //最后的排名
                $arrLastProject = [];
                foreach ($arrKidResultProject as $x => $y) {
                        //将数组里面的按分数从大到小排序
                        $arrSortProject = $this->arraySort($y, 'score');
                        //处理排名
                        foreach ($arrSortProject as $m => $n) {
                                $arrSortProject[$m]['ranking'] = $m + 1;
                        }

                        //处理相同的分数排名
                        $arrScore = [];
                        foreach ($arrSortProject as $k => $v) {
                                $newData['kidPhysicalTestResultId'] = $v['kidPhysicalTestResultId'];
                                if (!empty($arrScore) && $arrScore['score'] == $v['score']) {
                                        $intRanking = $arrScore['ranking'];
                                } else {
                                        $intRanking = $v['ranking'];
                                        $arrScore = $v;
                                }
                                $arrSortProject[$k]['ranking'] = $intRanking;
                                $newData['ranking'] = $intRanking;
                                $newData['upTime'] = $intTime;
                                $arrUpdateProjectRank[] = $newData;
                        }
                        //最后的排名
                        $arrLast = end($arrSortProject);
                        $arrLast['ranking'] = $arrLast['score'] == 0 ? $arrLast['ranking'] : $arrLast['ranking'] + 1;
                        $arrLastProject[$x] = $arrLast;
                }
                //一个项目没做的小孩
                $arrScoreInsert = [];
                //有小孩没有没做的项目(添加的项目)
                $arrInsertResult = [];

                foreach ($arrClassesKid as $k => $v) {
                        if (!in_array($v['kidId'], $arrPhysicalTestKid)) {
                                $strKidPhysicalTestScoreId = uuid();
                                $arrScoreInsert[] = [
                                        'kidPhysicalTestScoreId' => $strKidPhysicalTestScoreId,
                                        'institutionId' => $strInstitutionId,
                                        'physicalTestId' => $strPhysicalTestId,
                                        'startTime' => $intStartTime,
                                        'kidId' => $v['kidId'],
                                        'classesId' => $strClassesId,
                                        'score' => 0,
                                        'ranking' => 0,
                                        'isTest' => 2,
                                        'inTime' => $intTime,
                                ];
                                foreach ($arrProject as $x => $y) {
                                        //最后一名
                                        $intLastRanking = $arrLastProject[$y['projectId']]['ranking'];
                                        $strKidPhysicalTestResultId = uuid();
                                        $newData = [
                                                'kidPhysicalTestResultId' => $strKidPhysicalTestResultId,
                                                'institutionId' => $strInstitutionId,
                                                'physicalTestId' => $strPhysicalTestId,
                                                'kidId' => $v['kidId'],
                                                'classesId' => $strClassesId,
                                                'projectId' => $y['projectId'],
                                                'value' => 0,
                                                'score' => 0,
                                                'ranking' => $intLastRanking,
                                                'isTest' => 2,
                                                'inTime' => $intTime,
                                        ];
                                        $arrInsertResult[] = $newData;
                                }

                        }
                }

                //获取已经做过的小孩，还有哪些项目没有做
                foreach ($arrPhysicalTestProject as $k => $v) {
                        $kidId = $k;
                        $intAllScore = 0;
                        if (!empty($v)) {
                                $arrKidSelectProjectId = array_column($v, 'projectId');
                                foreach ($arrProject as $x => $y) {
                                        if (!in_array($y['projectId'], $arrKidSelectProjectId)) {
                                                //最后一名
                                                $intLastRanking = $arrLastProject[$y['projectId']]['ranking'];
                                                $strKidPhysicalTestResultId = uuid();
                                                $newData = [
                                                        'kidPhysicalTestResultId' => $strKidPhysicalTestResultId,
                                                        'institutionId' => $strInstitutionId,
                                                        'physicalTestId' => $strPhysicalTestId,
                                                        'kidId' => $kidId,
                                                        'classesId' => $strClassesId,
                                                        'projectId' => $y['projectId'],
                                                        'value' => 0,
                                                        'score' => 0,
                                                        'ranking' => $intLastRanking,
                                                        'isTest' => 2,
                                                        'inTime' => $intTime,
                                                ];
                                                $arrInsertResult[] = $newData;
                                        }
                                }
                                foreach ($v as $m => $n) {
                                        $intAllScore = $intAllScore + $n['score'];
                                }
                        }


                        $strKidPhysicalTestScoreId = uuid();
                        $arrScoreInsert[] = [
                                'kidPhysicalTestScoreId' => $strKidPhysicalTestScoreId,
                                'institutionId' => $strInstitutionId,
                                'physicalTestId' => $strPhysicalTestId,
                                'startTime' => $intStartTime,
                                'kidId' => $kidId,
                                'classesId' => $strClassesId,
                                'score' => $intAllScore,
                                'ranking' => 0,
                                'isTest' => 1,
                                'inTime' => $intTime,
                        ];
                }

                //总分排名
                if ($arrScoreInsert) {
                        //将数组里面的按分数从大到小排序
                        $arrSortScore = $this->arraySort($arrScoreInsert, 'score');
                        //处理排名
                        foreach ($arrSortScore as $m => $n) {
                                $arrSortScore[$m]['ranking'] = $m + 1;
                        }
                        //处理相同的分数排名
                        $arrScore = [];
                        foreach ($arrSortScore as $k => $v) {
                                if (!empty($arrScore) && $arrScore['score'] == $v['score']) {
                                        $intRanking = $arrScore['ranking'];
                                } else {
                                        $intRanking = $v['ranking'];
                                        $arrScore = $v;
                                }
                                $arrSortScore[$k]['ranking'] = $intRanking;
                        }

                        $arrScoreInsert = $arrSortScore;
                }


                //var_dump($arrUpdateProjectRank);
                //var_dump($arrScoreInsert);
                DB::connection('db.pool')->beginTransaction();// 需指定连接池时
                //添加项目
                if (!empty($arrInsertResult)) {
                        //添加
                        $bool = KidPhysicalTestResultModel::insert($arrInsertResult);
                        if (!$bool) {
                                DB::connection('db.pool')->rollBack();// 需指定连接池时
                                return ['code' => 304, 'msg' => '保存失败，添加结果记录错误'];
                        }
                }
                //更新项目排民
                if (!empty($arrUpdateProjectRank)) {
                        //批量更新
                        $bool = KidPhysicalTestResultModel::batchUpdateByIds($arrUpdateProjectRank);
                        if (!$bool) {
                                DB::connection('db.pool')->rollBack();// 需指定连接池时
                                return ['code' => 304, 'msg' => '保存失败，添加结果记录错误'];
                        }
                }
                //添加总分
                if (!empty($arrScoreInsert)) {
                        $bool = KidPhysicalTestScoreModel::insert($arrScoreInsert);
                        if (!$bool) {
                                DB::connection('db.pool')->rollBack();// 需指定连接池时
                                return ['code' => 304, 'msg' => '保存失败，添加总分排名失败'];
                        }
                }
                DB::connection('db.pool')->commit();// 需指定连接池时
                return ['code' => 0, 'msg' => '更新成功'];

        }

        /**
         * 获取体测分数
         * @param $strPhysicalTestId
         * @return array
         */
        public function actPhysicalTestScoreName($strPhysicalTestId)
        {
                $arrWhere = [
                        'physicalTestId' => $strPhysicalTestId,
                ];
                $arrField = ['projectId'];
                $arrProject = PhysicalTestProjectModel::getAll($arrWhere, $arrField);
                $arrProjectId = array_column($arrProject, 'projectId');
                $arrWhere = [
                        ['whereIn', 'projectId', $arrProjectId]
                ];
                $arrField = ['projectId', 'score', 'name', 'des'];
                $arrResultProject = ProjectScoreNameModel::getAll($arrWhere, $arrField);
                $arrNewProject = [];
                foreach ($arrResultProject as $k => $v) {
                        $arrNew['physicalTestId'] = $strPhysicalTestId;
                        $arrNew['projectId'] = $v['projectId'];
                        $arrNew['score'] = $v['score'];
                        $arrNew['name'] = $v['name'];
                        $arrNew['des'] = $v['des'];
                        $arrNewProject[] = $arrNew;
                }
                if (!$arrNewProject) return ['code' => 304, 'msg' => '添加失败,添加体测项目得分名称描述失败'];
                PhysicalTestScoreNameModel::insert($arrNewProject);
                return ['code' => 304, 'msg' => '添加成功,添加体测项目得分名称描述失败'];
        }

        /**
         * 二维数组根据某个字段排序
         * @param array $array 要排序的数组
         * @param string $keys 要排序的键字段
         * @param string $sort 排序类型  SORT_ASC     SORT_DESC
         * @return array 排序后的数组
         */
        function arraySort($array, $keys, $sort = SORT_DESC)
        {
                $keysValue = [];
                foreach ($array as $k => $v) {
                        $keysValue[$k] = $v[$keys];
                }
                array_multisort($keysValue, $sort, $array);
                return $array;
        }
}